/***********************************************************************
 * Module:  Pion.java
 * Author:  nabil
 * Purpose: Defines the Class Pion
 ***********************************************************************/
package model.jeu_de_dame;
import model.util.Couleur;
import model.util.Direction;
import model.gestion_mouvement.*;
import java.util.*;
import model.gestion_mouvement.IPiece;

/**
 * <b>Pion représente une piece particuliere du jeu de dame. Elle étend Piece.
 * </b>
  * <p>
 * Un pion est caractérisé par les informations suivantes :
 * <ul>
 * <li>La direction dans laquelle elle doit aller.</li>
 * </ul>
 * </p>
 * @see Damier
 * @see Piece
 * @author nabil mansouri
 * @version 2.0
 */
public class Pion extends Piece {
    /**
         * La direction du pion HAUT ou BAS
         * 
         * @see Damier#Damier() 
         * @see Pion#getDirection() 
         */
    
    
        public Pion(Damier monDamier,int x, int y,Couleur couleur)
        {
            super(monDamier,x,y,couleur);
        }
           /**
         * Constructeur Pion.
         * <p>
         * Initialisation du pion avec les coordonnées de la case x et y. Cette méthode affecte
         * la couleur au pion et une référence vers le Damier ainsi que sa direction.
         * </p>
         * @param monDamier 
         *           la référence vers le damier auquel elle appartient
         *@param  x
         *           la position x du pion 
         *@param  y
         *           la position y du pion 
         *@param  couleur
         *           la couleur du pion  
         *@param  dir
         *           la direction du pion 
         *  
         */
    public Pion(Damier monDamier,int x, int y,Couleur couleur,Direction dir)
    {
        this(monDamier,x,y,couleur);
        destination = dir;
    }
    
       /**Retourne la direction du pion
     * @return HAUT si la piece vas vers le haut BAS sinon
     */
     public Direction getDirection()
    {
        return this.destination;
    }
    
      /**Retourne la liste des cases accessible par le pion
     * @return Retourne la liste des cases accessible par le pion
     */
    public ArrayList<Case> getCasesAccessibles()
    {
        ArrayList<Case> lesCases = new ArrayList<Case>();
        ArrayList<ArrayList<Case>> lesChemins = this.getCase().getMesVoisines(2);
        boolean peutManger = false;
        for(ArrayList<Case> chemin : lesChemins)
        {//comme on a mis une profondeur de 2, les chemins sont forcément de longueur minimum 2
           if(chemin.size()==2)//dans ce cas on doit manger
           {
               if(chemin.get(0).hasPiece() && chemin.get(0).getPiece().isEnnemie(this) && !chemin.get(1).hasPiece())
               {//si c est ok on mange la piece puis on se deplace
                   if(!peutManger)
                       lesCases.clear();
                   lesCases.add(chemin.get(1));
                   peutManger = true;
               }
               else if(!chemin.get(0).hasPiece() && !peutManger && this.isDeplacementAvant(chemin.get(0))){
                   lesCases.add(chemin.get(0));
               }
           }
           else  if(chemin.size()==1)
           {
               if(!chemin.get(0).hasPiece()){
                   lesCases.add(chemin.get(0));
           }
           }
                     
        }
        
        return lesCases;
    }
    
    public boolean peutBouger()
    {
       return !this.getCasesAccessibles().isEmpty();
    }
         /**
     * @return true si le pion peut manger false sinon
     */
    public boolean peutManger()
    {
        ArrayList<ArrayList<Case>> lesChemins = this.getCase().getMesVoisines(2);
        for(ArrayList<Case> chemin : lesChemins)
        {//comme on a mis une profondeur de 2, les chemins sont forcément de longueur minimum 2
           if(chemin.size()==2)//dans ce cas on doit manger
           {
               if(chemin.get(0).hasPiece() && chemin.get(0).getPiece().isEnnemie(this) && !chemin.get(1).hasPiece())
               {//si c est ok on mange la piece puis on se deplace
                   return true;
               }
           }
            
        }
        return false;
    }
    
   /**Retourne si le pion peut se déplacer ou non. Dans cette méthode, le chemin
     * est parcouru. Les regles suivantes sont respectées:
     * <ul><li>La case d'arrivé est vide</li>
     * <li>La case d'arrivé doit exister</li>
     * <li>La case doit être autorisé</li>
     * <li>Le pion ne peut reculer que pour manger</li>
     * <li>Le pion ne peut pas se déplacer de plus d'une case (sauf pour manger)</li></ul>
     * @return true si le pion s'est déplacé false sinon
     */
    public boolean seDeplacer(Case arrive)
    {
        FactoryMouvementPion fact = FactoryMouvementPion.getInstance();
        MouvementValidator valid = fact.createValidateur();
        valid.setArrive(arrive);
        valid.setDepart(this.getCase());
        valid.setCouleur(couleur);
        valid.setDirection(this.getDirection());
        if(valid.isValid())
        {
           this.aManger = valid.peutManger();
           for(IPiece p : valid.getPieceAManger())
           {
               this.manger((Piece)p);
           }
           this.effectuerDeplacement(arrive);
           if(this.isDame())
                this.transformerEnDame();
           return true;
       }
       return false;
    }
                  
           
    
    /**@param arrive
     *          La case vers laquelle se deplace le pion
     * @return  true si la piece se daplace vers l'avant
     */
    private boolean isDeplacementAvant(Case arrive)
    {
        int deltaY = arrive.getPositionY()- this.positionY;
        if(this.destination == Direction.SUD )
        {
            if(deltaY > 0)
                return true;
        }
        else
        {
            if(deltaY < 0)
                return true;
        }
        return false;
        
            
    }
   
      /** Retourne si le pion se situe sur une case qui lui permet de se transformer en dame.
     * @return  true si le pion doit se transformer en dame. false sinon
     */
   private boolean isDame()
   {
       if(this.destination == Direction.SUD )
        {
            if(this.positionY == Damier.getTaille()-1)
                return true;
        }
        else
        {
             if(this.positionY == 0)
                return true;
        }
        return false;
   }
   
  
   
    /** Transforme le pion en dame.
      * @see  Pion#isDame() 
     */
   private void transformerEnDame()
   {
       Dame dame = new Dame(this);
       this.monDamier.setPiece(dame, positionX, positionY);
   }

   
    public ArrayList<Case> getCheminOffensif() {
        MouvementCalculateurPion p = new MouvementCalculateurPion(this); 
        ArrayList<Case> res = new ArrayList<Case>();  
        for(ICase c : p.getCheminOffensif())
            res.add((Case)c);
        return res;
    }

    @Override
    public ArrayList<Case> getPlusSurChemins() {
               MouvementCalculateurPion p = new MouvementCalculateurPion(this); 
        ArrayList<Case> res = new ArrayList<Case>();  
        for(ICase c : p.getPlusSureChemin())
            res.add((Case)c);
        return res;
    }

   
}